package com.g0dkar.leet.validation;

import java.util.HashSet;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

import br.com.caelum.vraptor.ioc.Component;

/**
 * <p>
 * This class centers all validation related methods. It depends a lot on Java's Bean Validation API (JSF 303). The
 * Framework's default API implementation is the <a href="http://validator.hibernate.org/">Hibernate Validator</a>.
 * </p>
 * 
 * <p>
 * This class is intended to be a facade to the Bean Validation API.
 * </p>
 * 
 * @author Daniel Mário
 * @author g0dkar
 * 
 */
@Component
public class LeetValidation {
	private static ValidatorFactory factory;
	
	static {
		factory = Validation.buildDefaultValidatorFactory();
	}
	
	private Set<ConstraintViolation<Object>> violations;
	
	/**
	 * Validate the given object, keeping all {@link ConstraintViolation ConstraintViolations}.
	 */
	public LeetValidation validate(Object object) {
		return setViolations(getValidator().validate(object));
	}

	private LeetValidation setViolations(Set<ConstraintViolation<Object>> newViolations) {
		if (violations == null) {
			violations = new HashSet<ConstraintViolation<Object>>();
		}
		
		violations.addAll(newViolations);
		return this;
	}

	private Validator getValidator() {
		Validator validator = null;
		synchronized (factory) {
			validator = factory.getValidator();
		}
		return validator;
	}
	
	/**
	 * Validates the given property of a object, keeping all {@link ConstraintViolation}s.
	 */
	public LeetValidation validateProperty(Object object, String propertyName) {
		return setViolations(getValidator().validateProperty(object, propertyName));
	}
	
	/**
	 * @return All violations from validated objects, or an empty set if there was nothing.
	 */
	public Set<ConstraintViolation<Object>> getViolations() {
		return violations;
	}
}
